package com.gopay.common.util.cbrmb.masapay;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gopay.common.util.cbrmb.exchange.JacksonUtil;

// 动态构造调用串，灵活性更大
public class MasaPayWebServiceUtils {

	private static Logger logger = LoggerFactory.getLogger(MasaPayWebServiceUtils.class);

	private String namespace;
	private String methodName;
	private String wsdlLocation;
	private String soapResponseData;

	public MasaPayWebServiceUtils(String namespace, String methodName, String wsdlLocation) {
		this.namespace = namespace;
		this.methodName = methodName;
		this.wsdlLocation = wsdlLocation;
	}

	private int invoke(Map<String, String> patameterMap) throws Exception {
		PostMethod postMethod = new PostMethod(wsdlLocation);
		String soapRequestData = buildRequestData(patameterMap);

		byte[] bytes = soapRequestData.getBytes("utf-8");
		InputStream inputStream = new ByteArrayInputStream(bytes, 0, bytes.length);
		RequestEntity requestEntity = new InputStreamRequestEntity(inputStream, bytes.length,
				"application/soap+xml; charset=utf-8");
		postMethod.setRequestEntity(requestEntity);

		HttpClient httpClient = new HttpClient();
		int statusCode = httpClient.executeMethod(postMethod);
		soapResponseData = postMethod.getResponseBodyAsString();

		return statusCode;
	}

	private String buildRequestData(Map<String, String> patameterMap) {
		StringBuffer soapRequestData = new StringBuffer();
		// soapRequestData.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
		soapRequestData.append(
				"<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ref=\"refundMerchantOrder\">");
		soapRequestData.append("<soapenv:Header/>");
		soapRequestData.append("<soapenv:Body>");
		soapRequestData.append("<ref:refund>");
		soapRequestData.append("<refundReqDTO>");

		Set<String> nameSet = patameterMap.keySet();
		for (String name : nameSet) {
			soapRequestData.append("<" + name + ">" + patameterMap.get(name) + "</" + name + ">");
		}
		soapRequestData.append("</refundReqDTO>");
		soapRequestData.append("</ref:refund>");
		soapRequestData.append("</soapenv:Body>");
		soapRequestData.append("</soapenv:Envelope>");

		return soapRequestData.toString();
	}

	/**
	 * @param args
	 * @throws Exception
	 */
	public static String post(String url, Map<String, String> params) throws Exception {
		MasaPayWebServiceUtils dynamicHttpclientCall = new MasaPayWebServiceUtils("refundMerchantOrder",
				"refundMerchantOrder", url);
		// 创建参数队列
		String soapRequestData = dynamicHttpclientCall.buildRequestData(params);
		logger.info(String.format("masapay refund req:", soapRequestData));
		int statusCode = dynamicHttpclientCall.invoke(params);
		String resp = null;
		if (statusCode == 200) {
			logger.info("调用成功！");
			String result = dynamicHttpclientCall.soapResponseData;
			resp = getRoot(result);
		} else {
			logger.error("调用失败！错误码：" + statusCode);
		}
		return resp;
	}

	public static String getRoot(String xmlString) throws DocumentException {
		Document document = DocumentHelper.parseText(xmlString);
		final Element root = document.getRootElement();// 获取根节点
		Map<String, String> resultMap = new HashMap<String, String>();
		getNodesIsTextNotNull(resultMap, root);
		return JacksonUtil.writeValueAsString(resultMap);
	}

	// 从指定节点Element node开始,递归遍历其所有子节点*/
	@SuppressWarnings("unchecked")
	public static void getNodesIsTextNotNull(Map<String, String> resultMap, final Element node) {
		String name = node.getName();
		String textTrim = node.getTextTrim();
		if (StringUtils.isNotEmpty(textTrim)) {
			logger.info("节点名称：" + name + ",节点内容：" + textTrim);
			resultMap.put(name, textTrim);
		}
		// 递归遍历当前节点所有的子节点
		final List<Element> listElement = node.elements();// 所有一级子节点的list
		for (final Element e : listElement) {// 遍历所有一级子节点
			getNodesIsTextNotNull(resultMap, e);// 递归
		}
	}

	// 从指定节点Element node开始,递归遍历其所有子节点*/
	@SuppressWarnings("unchecked")
	public static void getNodes(final Element node) {
		System.out.println("-------开始新节点-------------");
		// 当前节点的名称、文本内容和属性
		System.out.println("当前节点名称：" + node.getName());// 当前节点名称
		System.out.println("当前节点的内容：" + node.getTextTrim());// 当前节点内容
		final List<Attribute> listAttr = node.attributes();// 当前节点的所有属性
		for (final Attribute attr : listAttr) {// 遍历当前节点的所有属性
			final String name = attr.getName();// 属性名称
			final String value = attr.getValue();// 属性的值
			System.out.println("属性名称：" + name + "---->属性值：" + value);
		}
		// 递归遍历当前节点所有的子节点
		final List<Element> listElement = node.elements();// 所有一级子节点的list
		for (final Element e : listElement) {// 遍历所有一级子节点
			getNodes(e);// 递归
		}
	}

}